#include <ostream>
#include <mono/parser/property_tree_printer.h>
#include <mono/parser/property_node.h>

namespace mono {

PropertyTreePrinter::PropertyTreePrinter(std::ostream & output) 
	: _output(output)
	, _bracketOwnLine(false)
	, _indentLevel("\t")
{
}

void PropertyTreePrinter::print(const PropertyNodePtr & tree, bool printRoot) const {
	if (printRoot) {
		printStep(tree, 0);
	} else {
		for (size_t i = 0; i < tree->getNumNodes(); ++i)
			printStep(tree->getNode(i), 0);
	}
}

void PropertyTreePrinter::printStep(const PropertyNodePtr & node, size_t level) const {
	std::string outerIndent = getLevelIndent(level);
	std::string innerIndent = getLevelIndent(level + 1);
	
	_output << outerIndent << formatString(node->getName()) << " ";
	
	std::string tmp;
	for (size_t i = 0; i < node->getNumAttributes(); ++i) {
		tmp.clear();
		node->getAttribute(i, tmp);
		_output << formatString(tmp) << " ";
	}
	
	if (_bracketOwnLine)
		_output << "\n" << outerIndent << "{\n";
	else
		_output << "{\n";
	
	for (size_t i = 0; i < node->getNumProperties(); ++i) {
		Property property;
		node->getProperty(i, property);

		_output << innerIndent << formatString(property.first) << " " << formatString(property.second) << "\n";
	}
		
	if (node->getNumProperties() > 0 && node->getNumNodes() > 0)
		_output << "\n";
	
	for (size_t i = 0; i < node->getNumNodes(); ++i) {
		printStep(node->getNode(i), level + 1);
		
		if (i < node->getNumNodes() - 1)
			_output << "\n";
	}
	
	_output << outerIndent << "}\n";
}

std::string PropertyTreePrinter::formatString(const std::string & text) const {
	// use quotation marks around string if there's a whitespace in there
	std::string ret;
	
	if (text.find(" ") != std::string::npos || text.find("\t") != std::string::npos)
		ret = "\"" + text + "\"";
	else
		ret = text;
	
	return ret;
}

std::string PropertyTreePrinter::getLevelIndent(size_t level) const {
	std::string ret;
	for (size_t i = 0; i < level; ++i)
		ret += _indentLevel;
	
	return ret;
}

}
